#ifndef _M_T_P_
#define _M_T_P_

#include "Thread.hpp"
#include "Log.hpp"
#include "BlockingQueue.hpp"
#include "LockGuard.hpp"
#include <pthread.h>
#include <vector>
#include <queue>
#include <iostream>
#include <unistd.h>

using namespace ThreadModule;
using namespace LogModule;

const static int g_default = 5;

void test()
{
    while (true)
    {
        std::cout << "thread is running..." << std::endl;
        sleep(1);
    }
}

template <class T>
class ThreadPool
{
private:
    // 给任务队列加锁
    void LockQueue()
    {
        pthread_mutex_lock(&_mutex);
    }
    // 给任务队列解锁
    void UnLockQueue()
    {
        pthread_mutex_unlock(&_mutex);
    }
    // 在 _cond 条件下阻塞等待
    void Sleep()
    {
        pthread_cond_wait(&_cond, &_mutex);
    }
    // 唤醒一个休眠的线程
    void WakeUp()
    {
        pthread_cond_signal(&_cond);
    }
    // 唤醒所有休眠的线程
    void WakeUpAll()
    {
        pthread_cond_broadcast(&_cond);
    }
    // 判断任务队列是否为空
    bool IsEmpty()
    {
        // return _task_queue.empty();
        return _task_queue.IsEmpty();
    }
    // 处理任务 -> 消费者
    void HandlerTask(const std::string &name)
    {
        while (true)
        {
            LockQueue();
            // 任务队列为空
            while (IsEmpty() && _is_running)
            {
                LOG(INFO, "%s sleep begin\n", name.c_str());
                _sleep_thread_num++;
                Sleep(); // 阻塞等待
                _sleep_thread_num--;
                LOG(INFO, "%s wake up\n", name.c_str());
            }
            // 如果任务队列为空 && 线程池的状态为 退出
            if (IsEmpty() && !_is_running)
            {
                UnLockQueue();
                LOG(INFO, "%s quit...\n", name.c_str());
                break;
            }
            // 获取任务
            // T t = _task_queue.front();
            // _task_queue.pop();
            T t;
            _task_queue.Pop(&t);
            UnLockQueue();
            // 处理任务
            t(); // 注意这里的处理任务不应该放在临界区因为处理任务也费时间
            // std::cout << name << ": " << t.result() << std::endl;
            // LOG(DEBUG, "%s handler task: %s\n", name.c_str(), t.result().c_str());
        }
    }

    // 私有化构造
    ThreadPool(int thread_num = g_default)
        : _thread_num(thread_num), _sleep_thread_num(0), _is_running(false)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
    }

    // 删除或禁用赋值拷贝和拷贝构造
    ThreadPool(const ThreadPool &tp) = delete;
    ThreadPool &operator=(const ThreadPool &tp) = delete;

public:
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }

    // 创建获取单例对象的句柄静态函数 -> 懒汉式
    static ThreadPool *getInstance()
    {
        // 双重检查加锁
        if (_tp == nullptr)
        {
            // 加锁 -> RAII风格
            LockGuard lock(&_static_mutex);
            if (_tp == nullptr)
            {
                _tp = new ThreadPool<T>();
                _tp->Init();
                _tp->Start();
                LOG(INFO, "Create ThreadPool...\n");
            }
            else
            {
                LOG(INFO, "Get ThreadPool...\n");
            }
        }

        return _tp;
    }

    void Init()
    {
        func_t func = std::bind(&ThreadPool::HandlerTask, this, std::placeholders::_1);
        for (int i = 0; i < _thread_num; i++)
        {
            std::string threadname = "thread_" + std::to_string(i + 1);
            _threads.emplace_back(threadname, func);
            LOG(INFO, "%s is init success!\n", threadname.c_str());
        }
    }

    void Start()
    {
        LockQueue();

        _is_running = true;
        UnLockQueue();
        for (auto &t : _threads)
        {
            t.start();
            LOG(INFO, "%s is start...\n", t.get_name().c_str());
        }
    }

    void Stop()
    {
        LockQueue();
        LOG(INFO, "threadpool is stop...\n");
        _is_running = false;
        WakeUpAll();
        UnLockQueue();
    }

    // 向任务队列推送任务 -> 生产者
    void PushTask(T &task)
    {
        LockQueue();
        // 当线程池是启动的时候才允许推送任务
        if (_is_running)
        {
            _task_queue.Push(task);
            if (_sleep_thread_num > 0)
            {
                WakeUp();
            }
        }
        UnLockQueue();
    }

private:
    int _thread_num;              // 线程的数目
    std::vector<Thread> _threads; // 管理线程的容器
    // std::queue<T> _task_queue;    // 任务队列
    BlockingQueue<T> _task_queue; // 阻塞队列
    int _sleep_thread_num;        // 休眠线程的数目
    bool _is_running;             // 线程池的状态
    pthread_mutex_t _mutex;       // 互斥锁
    pthread_cond_t _cond;         // 条件变量

    static ThreadPool<T> *_tp;            // 单例模式
    static pthread_mutex_t _static_mutex; // 单例锁
};

// 类外初始化
template <class T>
ThreadPool<T> *ThreadPool<T>::_tp = nullptr;

template <class T>
pthread_mutex_t ThreadPool<T>::_static_mutex = PTHREAD_MUTEX_INITIALIZER;

#endif